﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace PlusPlusPaint.Layers.VisualObjects
{
    abstract class SizeAwareVisualObject : IVisualObject
    {
        #region member variables
        private int _sxSize, _sySize, cxPos, cyPos;
        #endregion

        #region properties
        protected abstract string ObjectTypeName
        {
            get;
        }

        protected int sxSize
        {
            get
            {
                return _sxSize;
            }
            set
            {
                _sxSize = Math.Max(value, 1);
            }
        }

        protected int sySize
        {
            get
            {
                return _sySize;
            }
            set
            {
                _sySize = Math.Max(value, 1);
            }
        }

        public abstract bool CanDrawOn
        {
            get;
        }

        public abstract bool AcceptsMostText
        {
            get;
        }

        public virtual Size Size
        {
            get
            {
                return new Size(sxSize, sySize);
            }
            set
            {
                this.sxSize = value.Width;
                this.sySize = value.Height;
            }
        }

        public Point Location
        {
            get
            {
                return new Point(cxPos, cyPos);
            }
            set
            {
                cxPos = value.X;
                cyPos = value.Y;
            }
        }

        public virtual Rectangle ClientRectangle
        {
            get
            {
                return new Rectangle(Location.X, Location.Y, Size.Width, Size.Height);
            }
        }
        #endregion

        #region abstract methods
        public abstract IVisualObject Clone();
        public abstract void BurnOn(Image im);
        public abstract bool PositionIsInHitbox(Point p);
        #endregion

        #region public methods
        public virtual void Deserialize(SerializedObject node)
        {
            if (node.UnnamedInts.Count < 2)
                throw new Exception("Insufficient int parameters to node.");
            this.cxPos = node.UnnamedInts[0];
            this.cyPos = node.UnnamedInts[1];
            this.sxSize = node.UnnamedInts[2];
            this.sySize = node.UnnamedInts[3];
            node.UnnamedInts.RemoveAt(3);
            node.UnnamedInts.RemoveAt(2);
            node.UnnamedInts.RemoveAt(1);
            node.UnnamedInts.RemoveAt(0);
            // remove the things that have been handled
        }

        public virtual SerializedObject Serialize()
        {
            List<int> unnamedInts = new List<int>();
            unnamedInts.Add(cxPos);
            unnamedInts.Add(cyPos);
            unnamedInts.Add(sxSize);
            unnamedInts.Add(sySize);
            return new SerializedObject(ObjectTypeName, unnamedInts);
        }

        public virtual void ResizeToBeIn(Point p1, Point p2)
        {
            SetBoxAround(p1, p2);
        }
        #endregion

        #region protected methods
        protected void SetBoxAround(Point p1, Point p2)
        {
            this.sxSize = Math.Abs(p1.X - p2.X);
            this.sySize = Math.Abs(p1.Y - p2.Y);
            this.Location = new Point(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y));
        }
        #endregion
    }
}
